<template>
  <!-- 查询表单 -->
  <a-collapse v-model:activeKey="activeKey" :bordered="false">
    <a-collapse-panel key="1" :style="customStyle" header="用户管理-查询">
      <a-row>
        <a-col :span="22">
          <a-form ref="queryFormRef" :model="queryFormState">
            <a-row :gutter="16">
              <a-col :span="6">
                <a-form-item label="用户名" name="username">
                  <a-input v-model:value="queryFormState.username" placeholder="请输入用户名" />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="昵称" name="nickname">
                  <a-input v-model:value="queryFormState.nickname" placeholder="请输入手机号" />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="状态" name="status">
                  <a-select
                    v-model:value="queryFormState.status"
                    :options="statusOptions"
                    placeholder="请选择状态"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="更新时间" name="updatedAt">
                  <a-range-picker style="width: 100%" @change="updated" />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="手机号" name="phone">
                  <a-input v-model:value="queryFormState.phone" placeholder="请输入手机号" />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="邮箱" name="email">
                  <a-input v-model:value="queryFormState.email" placeholder="请输入手机号" />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="角色" name="roleList">
                  <a-select
                    v-model:value="queryFormState.roleList"
                    :max-tag-count="1"
                    :options="roleOptions"
                    :filter-option="filterOption"
                    allow-clear
                    mode="multiple"
                    placeholder="请选择角色"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="6">
                <a-form-item label="创建时间" name="createdAt">
                  <a-range-picker style="width: 100%" @change="created" />
                </a-form-item>
              </a-col>
            </a-row>
          </a-form>
        </a-col>
        <a-divider style="height: 80px" type="vertical" />
        <a-col :span="1">
          <a-space :size="22" direction="vertical">
            <a-button type="primary" @click="onQuery">
              <template #icon>
                <SearchOutlined />
              </template>
              查询
            </a-button>
            <a-button @click="onReset">
              <template #icon>
                <ReloadOutlined />
              </template>
              重置
            </a-button>
          </a-space>
        </a-col>
      </a-row>
    </a-collapse-panel>
  </a-collapse>
  <!-- 数据表格 -->
  <a-card size="small">
    <a-button size="small" style="margin-bottom: 10px" type="primary" @click="modalVisible = true">
      <template #icon>
        <PlusOutlined />
      </template>
      添加
    </a-button>
    <a-button
      size="small"
      type="primary"
      danger
      :disabled="!hasSelected"
      :loading="rowSelectionState.loading"
      @click="start"
      style="margin-left: 10px"
    >
      <template #icon>
        <DeleteOutlined />
      </template>
      删除
    </a-button>
    <span style="margin-left: 8px">
      <template v-if="hasSelected">
        {{ `选择了 ${rowSelectionState.selectedRowKeys.length} 条数据` }}
      </template>
    </span>
    <!-- 表格 -->
    <a-table
      v-model:pagination="pagination"
      :columns="columns"
      :data-source="dataSource"
      :loading="loading"
      :scroll="{ x: '150%', y: 360 }"
      bordered
      rowKey="id"
      :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
      @change="handleTableChange"
    >
      <template #bodyCell="{ column, record }">
        <!-- 头像 -->
        <template v-if="column.dataIndex === 'avatar'">
          <a-image
            :alt="'用户' + record.nickname + '的头像'"
            :src="
              record.avatar
                ? record.avatar
                : 'https://tse1-mm.cn.bing.net/th/id/OIP-C.-_yfZXrSVz_QznD9xTYraQAAAA?w=209&h=210&c=7&r=0&o=5&dpr=1.3&pid=1.7'
            "
            :width="30"
          />
        </template>
        <!-- 是否禁用 -->
        <template v-if="column.dataIndex === 'status'">
          <template v-if="record.status === 1">
            <div class="disabled"></div>
          </template>
          <template v-else>
            <div class="enable"></div>
          </template>
        </template>
        <!-- 角色 -->
        <template v-if="column.dataIndex === 'roleList'">
          <a-popover v-if="record.roleList.length > 1" trigger="hover">
            <a-badge
              :count="record.roleList.length"
              :dot-style="{
                background: '#E5E6EB',
                color: '#86909C'
              }"
            >
              <a-space style="cursor: pointer">
                <a-tag bordered>{{ record.roleList[0].roleName }}</a-tag>
                ...
              </a-space>
            </a-badge>
            <template #content>
              <div style="width: 200px">
                <a-space fill size="small" wrap>
                  <template v-for="role in record.roleList" :key="role.index">
                    <a-tag bordered> {{ role.roleName }}</a-tag>
                    <span v-if="role.index % 2 == 0">000</span>
                  </template>
                </a-space>
              </div>
            </template>
          </a-popover>
          <template v-else-if="record.roleList.length == 1">
            <a-tag bordered>{{ record.roleList[0].roleName }}</a-tag>
          </template>
          <template v-else> 暂无角色信息</template>
        </template>
        <!-- 操作 -->
        <template v-if="column.dataIndex === 'operations'">
          <div class="action">
            <a-button size="small" type="primary" @click="onEdit(record.id)">
              <template #icon>
                <EditOutlined />
              </template>
            </a-button>
            <a-popconfirm cancel-text="×" ok-text="√" title="删除？" @confirm="confirm">
              <a-button danger size="small" type="primary" @click="onDelete(record.id)">
                <template #icon>
                  <DeleteOutlined />
                </template>
              </a-button>
            </a-popconfirm>
          </div>
        </template>
      </template>
    </a-table>
  </a-card>
  <!-- 新增数据模态框 -->
  <a-modal v-model:visible="modalVisible" title="添加用户" @cancel="handleCancel" @ok="handleOk">
    <a-form ref="addFormRef" :model="addFormState" :rules="addFormRules" layout="vertical">
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="用户名" name="username">
            <a-input v-model:value="addFormState.username" placeholder="请输入用户名" />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="昵称" name="nickname">
            <a-input v-model:value="addFormState.nickname" placeholder="请输入昵称"></a-input>
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="手机号" name="phone">
            <a-input
              v-model:value="addFormState.phone"
              addon-before="+86"
              placeholder="请输入手机号"
            />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="密码" name="password">
            <a-input-password
              v-model:value="addFormState.password"
              placeholder="请输入密码，默认123456"
            />
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="邮箱" name="email">
            <a-input v-model:value="addFormState.email" placeholder="请输入邮箱" />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="状态" name="status">
            <a-select
              v-model:value="addFormState.status"
              :options="statusOptions"
              placeholder="请选择是否禁用"
            />
          </a-form-item>
        </a-col>
      </a-row>
    </a-form>
  </a-modal>
  <!-- 更新数据抽屉 -->
  <a-drawer
    :body-style="{ paddingBottom: '80px' }"
    :footer-style="{ textAlign: 'right' }"
    :visible="drawerVisible"
    :width="720"
    title="编辑用户信息"
    @close="onClose"
  >
    <a-form ref="updateFormRef" :model="updateFormState" :rules="updateFormRules" layout="vertical">
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="用户名" name="username">
            <a-input v-model:value="updateFormState.username" placeholder="请输入用户名" />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="昵称" name="nickname">
            <a-input v-model:value="updateFormState.nickname" placeholder="请输入昵称"></a-input>
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="手机号" name="phone">
            <a-input
              v-model:value="updateFormState.phone"
              addon-before="+86"
              placeholder="请输入手机号"
            />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="邮箱" name="email">
            <a-input v-model:value="updateFormState.email" placeholder="请输入邮箱" />
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col :span="12">
          <a-form-item label="状态" name="status">
            <a-select
              v-model:value="updateFormState.status"
              :options="statusOptions"
              placeholder="请选择状态"
            />
          </a-form-item>
        </a-col>
        <a-col :span="12">
          <a-form-item label="角色" name="roleList">
            <a-select
              v-model:value="updateFormState.roleList"
              :max-tag-count="2"
              :options="roleOptions"
              :filter-option="filterOption"
              allow-clear
              mode="multiple"
              placeholder="请选择角色信息"
            />
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-form-item label="用户头像" name="avatar">
          <a-input v-model:value="updateFormState.avatar" hidden />
          <a-upload
            v-model:file-list="fileList"
            name="file"
            :headers="{ Authorization: getToken() }"
            list-type="picture-card"
            action="/api/file/uploadFile"
            :before-upload="beforeUpload"
            :maxCount="1"
            @change="handleChange"
          >
            <div>
              <LoadingOutlined v-if="uploadLoading" />
              <PlusOutlined v-else />
            </div>
          </a-upload>
        </a-form-item>
      </a-row>
    </a-form>
    <template #extra>
      <a-space>
        <a-button @click="onClose">取消</a-button>
        <a-button type="primary" @click="onFinish">提交</a-button>
      </a-space>
    </template>
  </a-drawer>
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref, toRefs } from 'vue'
import type {
  FormInstance,
  TableColumnType,
  TableProps,
  UploadChangeParam,
  UploadFile,
  UploadProps
} from 'ant-design-vue'
import { message, Upload } from 'ant-design-vue'
import { usePagination } from 'vue-request'
import { addUser, deleteByIds, getUserById, queryUserList, updateUser } from '@/api/user'
import type { Rule } from 'ant-design-vue/lib/form'
import type { AddUserDTO, QueryUserDTO, UpdateUserDTO, UserDTO } from '@/types/user'
import { queryAllRole } from '@/api/role'
import type { IntervalStrDTO } from '@/types/global'
import pinyin from 'tiny-pinyin'
import { getToken } from '@/utils/auth'
// 下拉列表自定义样式
const customStyle = 'background: #ffffff;' + 'margin-bottom: 10px;' + 'border: none;'
// 状态选择
const statusOptions = computed(() => [
  {
    label: '正常',
    value: 0
  },
  {
    label: '禁用',
    value: 1
  }
])

const roleOptions = reactive<{ label: string; value: number }[]>([])

onMounted(() => {
  queryAllRole()
    .then((res) => {
      // Array.map方法
      // roleOptions.value = res.data.data.map((role) => {
      //   return { label: role.name, value: role.id }
      // })
      // typescript中的forEach方法
      res.data.data.forEach((role) => {
        roleOptions.push({
          label: role.name,
          value: role.id
        })
      })
    })
    .catch((error) => {
      message.error(error)
    })
})
// 选择器中文搜索
const filterOption = (input: string, option: any) => {
  return (
    pinyin
      .convertToPinyin(option.label)
      .toLowerCase()
      .indexOf(pinyin.convertToPinyin(input).toLowerCase()) >= 0
  )
}
const queryFormRef = ref<FormInstance>()
const queryFormState = reactive<QueryUserDTO & IntervalStrDTO>({
  roleList: []
})
// 查询
const onQuery = () => {
  run({
    ...queryFormState
  })
}
// 重置
const onReset = () => {
  console.log('重置')
  queryFormRef.value?.resetFields()
}

// 选择更新时间间隔
const updated = (date: any, dateString: (string | undefined)[]) => {
  queryFormState.updatedAtStart = dateString[0]
  queryFormState.updatedAtEnd = dateString[1]
}
// 选择创建时间间隔
const created = (date: any, dateString: (string | undefined)[]) => {
  queryFormState.createdAtStart = dateString[0]
  queryFormState.createdAtEnd = dateString[1]
}

// 表格列配置
const columns: TableColumnType<UserDTO>[] = [
  {
    title: 'ID',
    dataIndex: 'id',
    fixed: 'left',
    align: 'center',
    sorter: true,
    width: 60
  },
  {
    title: '用户名',
    dataIndex: 'username',
    align: 'center',
    fixed: 'left',
    sorter: true
  },
  {
    title: '手机号',
    dataIndex: 'phone',
    align: 'center',
    // width: "100%",
    sorter: true
  },
  {
    title: '昵称',
    dataIndex: 'nickname',
    align: 'center',
    sorter: true
  },
  {
    title: '邮箱',
    dataIndex: 'email',
    align: 'center',
    ellipsis: true,
    sorter: true
  },
  {
    title: '头像',
    dataIndex: 'avatar',
    align: 'center'
  },
  {
    title: '状态',
    dataIndex: 'status',
    align: 'center'
  },
  {
    title: '角色',
    dataIndex: 'roleList',
    align: 'center',
    width: 200
  },
  {
    title: '创建时间',
    dataIndex: 'createdAt',
    align: 'center',
    sorter: true,
    width: 200
  },
  {
    title: '更新时间',
    dataIndex: 'updatedAt',
    align: 'center',
    sorter: true,
    width: 200
  },
  {
    title: '操作',
    dataIndex: 'operations',
    fixed: 'right',
    align: 'center'
  }
]

const activeKey = ref(['1'])

// 处理表格变化
const handleTableChange: TableProps['onChange'] = (pagination, filters: any, sorter: any) => {
  run({
    current: pagination.current,
    pageSize: pagination.pageSize,
    sortField: sorter.field,
    sortOrder: sorter.order,
    ...queryFormState
  })
}

const { data, total, run, loading, current, pageSize } = usePagination(queryUserList, {
  defaultParams: [
    {
      current: 1,
      pageSize: 10
    }
  ],
  pagination: {
    currentKey: 'current',
    pageSizeKey: 'pageSize',
    totalKey: 'data.data.total'
  }
})

// 分页数据
const pagination = computed(() => ({
  total: total.value,
  current: current.value,
  pageSize: pageSize.value
}))
// 用户数据
const dataSource = computed<UserDTO[]>(() => data.value?.data.data.records || [])

// 新增数据模态框是否可见
const modalVisible = ref<boolean>(false)
const addFormRef = ref<FormInstance>()
// 新增表单
const addFormState = ref<AddUserDTO>({
  username: '',
  password: '',
  phone: '',
  nickname: '',
  email: '',
  status: 0,
  avatar: ''
})

const handleOk = (e: MouseEvent) => {
  console.log(e)
  addUser(addFormState.value).then((res) => {
    const { code, msg } = res.data
    message.success(msg)
    if (code == 200) {
      addFormRef.value?.resetFields()
      modalVisible.value = false
      run({
        current: pagination.value.current,
        pageSize: pagination.value.pageSize,
        ...queryFormState
      })
    }
  })
}

const handleCancel = () => {
  addFormRef.value?.resetFields()
}

const addFormRules: Record<string, Rule[]> = {
  username: [{ required: true, message: '用户名不能为空' }],
  nickname: [{ required: true, message: '昵称不能为空' }],
  phone: [{ required: true, message: '请输入手机号' }]
}

// 抽屉是否可见
const drawerVisible = ref<boolean>(false)
const updateFormRef = ref<FormInstance>()
// 更新表单
const updateFormState = ref<UpdateUserDTO>({
  id: 0,
  username: '',
  phone: '',
  nickname: '',
  email: '',
  status: 0,
  avatar: '',
  roleList: []
})

const updateFormRules: Record<string, Rule[]> = {
  username: [{ required: true, message: '用户名不能为空' }],
  nickname: [{ required: true, message: '昵称不能为空' }],
  phone: [{ required: true, message: '请输入手机号' }]
}

// 编辑
const onEdit = (id: number) => {
  getUserById(id)
    .then((res) => {
      const { data } = res.data
      updateFormState.value = {
        id: data.id,
        username: data.username,
        phone: data.phone,
        nickname: data.nickname,
        email: data.email,
        status: data.status,
        roleList: data.roleList.map((userRole) => {
          return userRole.roleId
        }),
        avatar: data.avatar
      }
      if (data.avatar) {
        fileList.value.push({
          uid: '-1',
          name: '头像',
          url: data.avatar,
          status: 'done'
        })
      }
    })
    .catch((error) => {
      console.log(error)
    })
  showDrawer()
}
// 打开抽屉
const showDrawer = () => {
  drawerVisible.value = true
}
// 关闭抽屉
const onClose = () => {
  drawerVisible.value = false
  updateFormRef.value?.resetFields()
  fileList.value = []
}

// 提交编辑
const onFinish = () =>
  updateUser(updateFormState.value).then((res) => {
    const { code, msg } = res.data
    message.success(msg)
    if (code == 200) {
      onClose()
      run({
        current: pagination.value.current,
        pageSize: pagination.value.pageSize,
        ...queryFormState
      })
    }
  })

/**
 * ===============================删除==================================
 */
const idList = ref<number[]>([])
// 删除
const onDelete = (id: number) => {
  idList.value = [id]
}
const confirm = () => {
  if (idList.value.length > 0) {
    deleteByIds(idList.value).then((res) => {
      const { code, msg } = res.data
      if (code == 200) {
        message.success(msg)
        run({
          current: pagination.value.current,
          pageSize: pagination.value.pageSize,
          ...queryFormState
        })
      }
    })
  }
}
type Key = string | number
const rowSelectionState = reactive<{
  selectedRowKeys: Key[]
  loading: boolean
}>({
  selectedRowKeys: [],
  loading: false
})

const hasSelected = computed(() => rowSelectionState.selectedRowKeys.length > 0)
const { selectedRowKeys } = toRefs(rowSelectionState)
const onSelectChange = (selectedRowKeys: Key[]) => {
  rowSelectionState.selectedRowKeys = selectedRowKeys
}
const start = () => {
  rowSelectionState.loading = true
  deleteByIds(rowSelectionState.selectedRowKeys).then((res) => {
    const { code, msg } = res.data
    if (code == 200) {
      rowSelectionState.loading = false
      rowSelectionState.selectedRowKeys = []
      message.success(msg)
      run({ current: pagination.value.current, pageSize: pagination.value.pageSize })
    }
  })
}

// 图片上传
function getBase64(img: Blob | undefined, callback: (base64Url: string) => void) {
  const reader = new FileReader()
  reader.addEventListener('load', () => callback(reader.result as string))
  reader.readAsDataURL(img as Blob)
}

const fileList = ref<UploadFile[]>([])
const uploadLoading = ref<boolean>(false)

const handleChange = (info: UploadChangeParam) => {
  let resFileList = [...info.fileList]
  resFileList.forEach((file) => {
    if (file.response) {
      updateFormState.value.avatar = file.response.url
    }
  })
  if (info.file.status === 'uploading') {
    uploadLoading.value = true
    return
  }
  if (info.file.status === 'done') {
    uploadLoading.value = false
  }
  if (info.file.status === 'error') {
    uploadLoading.value = false
    message.error('上传错误')
  }
}

const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  const isPNG = file.type === 'image/png' || file.type === 'image/jpeg'
  if (!isPNG) {
    message.error(`${file.name} 类型的图片暂不支持`)
  }
  const isLt2M = file.size / 1024 / 1024 < 2
  if (!isLt2M) {
    message.error('请上传小于2MB的图片')
    return false
  }
  return (isPNG && isLt2M) || Upload.LIST_IGNORE
}
</script>
<style lang="less" scoped>
.action {
  button:first-child {
    margin-right: 5px;
  }

  button:last-child {
    margin-left: 5px;
  }
}

.disabled,
.enable {
  display: flex;
  justify-content: center;
  font-size: 12px;
}

.disabled::before {
  content: '';
  width: 8px;
  height: 8px;
  background-color: red;
  margin: auto 2px auto 0;
}

.disabled::after {
  content: '禁用';
  margin: auto 2px auto 0;
}

.enable::before {
  content: '';
  width: 8px;
  height: 8px;
  background-color: green;
  margin: auto 2px auto 0;
}

.enable::after {
  content: '启用';
  margin: auto 2px auto 0;
}
</style>
